<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Mapper\ChConfigGroupMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChRoomMapper;
use App\CustHub\Model\ChConfig;
use App\CustHub\Model\ChConfigValue;
use App\CustHub\Model\ChMaterial;
use App\CustHub\Model\ChMaterialTag;
use App\Setting\Service\SettingConfigService;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use function Hyperf\Collection\collect;

class ChConfigService extends AbstractService
{
    #[Inject]
    protected SettingConfigService $service;

    #[Inject]
    protected ChConfigGroupMapper $groupMapper;

    #[Inject]
    protected Redis $redis;

    protected string $cachePrefix = 'ch_config_group_v1:';

    public function getConfig(): array
    {
        $customerServiceQrCode = $this->service->getConfigByKey('professional_services');

        $result = [
            'customer_service_qrcode' => $customerServiceQrCode['value'] ?? '',
        ];

        return $result;
    }

    /**
     * 获取配置列表
     * @param mixed $uid
     * @param mixed $mainUid
     * @param mixed $groupKey
     * @return array
     */
    public function getConfigByGroupKey(mixed $uid,mixed $mainUid, mixed $groupKey): array
    {
        $groupInfo = $this->groupMapper->findByCode($groupKey);
        if(empty($groupInfo)){
            return [];
        }

        //是否区分员工账号
        $isDistEmpAcc = $groupInfo->is_dist_emp_acc;

        $cacheName = $this->cachePrefix.md5($uid.'-'.$mainUid.'-'.$groupKey.'-'.$isDistEmpAcc);

//        $list = $this->redis->get($cacheName);
//        if(!empty($list)){
//            return $list;
//        }

        $list = ChConfig::query()
            ->selectRaw('ch_config.id,ch_config.name,ch_config.key,ch_config.tips,ch_config.input_type,ch_config.config_select_data,ifnull(b.value,ch_config.value) as value')
            ->leftJoin('ch_config_value as b',function ($join) use ($uid,$mainUid,$isDistEmpAcc){
                if($isDistEmpAcc){
                    $join->on('ch_config.id','=','b.config_id')->where('b.uid',$uid);
                }else{
                    $join->on('ch_config.id','=','b.config_id')->where('b.main_uid',$mainUid)->where('b.uid',$mainUid);;
                }
            })
            ->where('ch_config.group_id',$groupInfo->id)
            ->orderByRaw('ch_config.sort desc,ch_config.id asc')
            ->get()->toArray();

        foreach ($list as $key=>$item){
            if(!empty($item['config_select_data'])){
                $item['config_select_data'] = json_decode($item['config_select_data'],true);
            }else{
                $item['config_select_data'] = [];
            }
            if(isJson($item['value'])){
                $item['value'] = json_decode($item['value'],true);
            }
            //素材采集群反写
            if($item['key']=='material_collect_person_config'){
                $material_collect_person_config=$item['value'];
                if(!empty($material_collect_person_config['room_config'])){
                    foreach ($material_collect_person_config['room_config'] as $key1=>$item1){
                        $material_collect_person_config['room_config'][$key1]['robot_info'] = container()->get(ChRobotMapper::class)->findById($item1['robot_id']);
                        $material_collect_person_config['room_config'][$key1]['room_info'] = container()->get(ChRoomMapper::class)->findByRoomWxid($item1['room_wxid'],$mainUid);
                        if(!empty($item1['tags'])){
                            $tagsArray = ChMaterialTag::query()->whereIn('id',$item1['tags'])->get(['name','id'])->toArray();
                            $material_collect_person_config['room_config'][$key1]['tags_info'] = $tagsArray;
                        }
                    }
                    $list[$key]['value']=json_encode($material_collect_person_config,256);
                }
            }
        }

        $list = array_column($list,null,'key');

        $this->redis->set($cacheName,$list,3600);
        return $list;
    }

    /**
     * 保存配置
     * @param array $params
     * @return bool
     */
    public function saveConfig(array $params): bool
    {
        $cfg = json_decode($params['cfg'],true);
        $mainUid = $params['main_uid'];
        $uid = $params['uid'];
        $groupInfo = $this->groupMapper->findByCode($params['group']);
        if(empty($groupInfo)){
            throw new NormalStatusException('配置组不存在');
        }

        //是否区分员工账号
        $isDistEmpAcc = $groupInfo->is_dist_emp_acc;

        $cfgCollect = collect($cfg);

        $configIdList = $cfgCollect->pluck('config_id')->toArray();

        $existingConfig = ChConfigValue::query()
            ->where(function ($query) use ($uid,$mainUid,$isDistEmpAcc){
                if($isDistEmpAcc){
                    $query->where('uid',$uid);
                }else{
                    $query->where('main_uid',$mainUid)->where('uid',$mainUid);
                }
            })
            ->whereIn('config_id',$configIdList)
            ->pluck('id','config_id');


        $data = $cfgCollect->transform(function ($item) use ($uid,$mainUid){
            $item['uid'] = $uid;
            $item['main_uid'] = $mainUid;
            return $item;
        });

        $toUpdate = $data->filter(fn($config) => $existingConfig->has($config['config_id']));
        $toInsert = $data->reject(fn($config) => $existingConfig->has($config['config_id']));

        if($toUpdate->isNotEmpty()){
            $toUpdate->transform(function ($item){
                $item['updated_at'] = Carbon::now()->toDateTimeString();
                is_array($item['value']) && $item['value'] = json_encode($item['value'],JSON_UNESCAPED_UNICODE);
                return $item;
            });
            if($isDistEmpAcc){
                $uniqueBy = ['uid','config_id'];
            }else{
                $uniqueBy = ['main_uid','config_id'];
            }
            ChConfigValue::upsert($toUpdate->toArray(), $uniqueBy);
        }

        if($toInsert->isNotEmpty()){
            $toInsert->transform(function ($item){
                $item['created_at'] = Carbon::now()->toDateTimeString();
                is_array($item['value']) && $item['value'] = json_encode($item['value'],JSON_UNESCAPED_UNICODE);
                return $item;
            });
            ChConfigValue::insert($toInsert->toArray());
        }
        $cacheName = $this->cachePrefix.md5($uid.'-'.$mainUid.'-'.$params['group'].'-'.$isDistEmpAcc);
        $this->redis->del([$cacheName]);
        return true;
    }


}